package main

import (
	"encoding/json"
	"fmt"
	"image"
	"image/jpeg"
	"image/png"
	"os"
	"time"

	// "path/filepath"
	// "strings"
	// "sync"

	"github.com/chai2010/webp"
)

const CODE_SUCCESS = 1;
const CODE_ERROR = 0;

// 使用结构体示例
type ResTypes struct {
	Msg string `json:"msg"`
	Code  int    `json:"code"`
	Ms  int64    `json:"ms"`
	SourceSize float32 `json:"sourceSize"`
	TargetSize float32 `json:"targetSize"`
	Rate float32 `json:"rate"`
}

var Res ResTypes;

// Res = ResTypes{Msg: "OK", Code: 1}

// PrintJSON 格式化并打印 JSON
func PrintJSON(data interface{}) {
	jsonBytes, err := json.MarshalIndent(data, "", "  ")
	if err != nil {
		fmt.Println("{\"code\":0,\"msg\":\"错误\"}")
		return
	}
	fmt.Println(string(jsonBytes))
}

func main() {
    // 获取开始时间（毫秒时间戳）
	start := time.Now().UnixNano() / int64(time.Millisecond)
	Res.Msg = "错误"
	Res.Code = CODE_ERROR
    // 检查命令行参数
	if len(os.Args) < 2 {
		// fmt.Println("使用方法: webp_compressor <图片路径> [质量(0-100)]")
		// fmt.Println("示例: webp_compressor /1.jpg 80")
		Res.Code = CODE_ERROR;
		Res.Msg = "参数错误 必须传递图片路径";
		PrintJSON(Res);
// 		os.Exit(1)
		return ;
	}

	imagePath := os.Args[1]
	quality := 75 // 默认质量

	// 如果有提供质量参数
	if len(os.Args) >= 3 {
		_, err := fmt.Sscanf(os.Args[2], "%d", &quality)
		if err != nil || quality < 0 || quality > 100 {
			// fmt.Printf("错误: 质量参数必须是 0-100 之间的整数\n")
			Res.Code = CODE_ERROR;
    		Res.Msg = "参数错误 质量参数必须是 0-100 之间的整数";
    		PrintJSON(Res);
// 			os.Exit(1)
            return ;
		}
	}
	// fmt.Printf("quality: %d ", quality);
	
	// 验证文件是否存在
	fileInfo, err := os.Stat(imagePath)
	if err != nil {
	    Res.Code = CODE_ERROR;
		Res.Msg = "参数错误 文件不存在";
		PrintJSON(Res);
		return ;
	}
	if os.IsNotExist(err) {
        Res.Code = CODE_ERROR;
		Res.Msg = "参数错误 文件不存在";
		PrintJSON(Res);
		return ;
	}
	
	// 获取文件大小（字节）
    fileSizeInBytes := fileInfo.Size()
    
    // 转换为MB（float32类型）
    Res.SourceSize = float32(fileSizeInBytes) / (1024 * 1024)
    Res.SourceSize = float32(int32(Res.SourceSize*100)) / 100
    

	// 打开图片文件
	file, err := os.Open(imagePath)
	if err != nil {
		// fmt.Printf("错误: 无法打开文件: %v\n", err)
		Res.Code = CODE_ERROR;
		Res.Msg = "参数错误 无法打开文件";
		PrintJSON(Res);
		return ;
		// os.Exit(1)
	}
	defer file.Close()

    err = compressImage1(imagePath, quality)
    if err != nil {
        Res.Code = CODE_ERROR;
		Res.Msg = err.Error();
		PrintJSON(Res);
		return ;
    }

	// fmt.Println("✅ 批量压缩完成！")
	
	newFileInfo, err := os.Stat(imagePath)
	// 转换为MB（float32类型）
    Res.TargetSize = float32(newFileInfo.Size()) / (1024 * 1024)
	Res.TargetSize = float32(int32(Res.TargetSize*100)) / 100
	
    if Res.TargetSize < Res.SourceSize {
        rate := (Res.SourceSize - Res.TargetSize) / Res.SourceSize
        Res.Rate = float32(int32(rate*10000)) / 100    
    }
	
	Res.Code = CODE_SUCCESS;
	Res.Msg = "ok";
	PrintJSON(Res);
	// 获取结束时间（毫秒时间戳）
	end := time.Now().UnixNano() / int64(time.Millisecond)
	// 计算执行时间（毫秒）
	Res.Ms = end - start
	return ;
}
// 压缩单张图片
func compressImage1(path string, quality int) error {
    // fmt.Printf("path:%s \n\r", path)
	inFile, err := os.Open(path)
	if err != nil {
		return err
	}
	defer inFile.Close()

	img, format, err := image.Decode(inFile)
	if err != nil {
		return fmt.Errorf("解码失败: %w", err)
	}

	outFile, err := os.Create(path)
	if err != nil {
		return err
	}
	defer outFile.Close()

	switch format {
    	case "jpeg":
    		err = jpeg.Encode(outFile, img, &jpeg.Options{Quality: quality})
    	case "png":
    		encoder := png.Encoder{CompressionLevel: png.BestCompression}
    		err = encoder.Encode(outFile, img)
    	case "webp":
    		err = webp.Encode(outFile, img, &webp.Options{Quality: float32(quality)})
    	default:
    		return fmt.Errorf("不支持的格式: %s", format)
	}
	return err
}
